﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace decode
{
    class Cl_workflow
    {

        /// <summary>
        /// Langue choisie par l'utilisateur par défaut all
        /// </summary>
        private string langue = "all";
        /// <summary>
        /// Chrono pour calculer le temps
        /// </summary>
        private Stopwatch chrono;
        /// <summary>
        /// Chrono pour toutes les méthodes de cryptage
        /// </summary>
        private Stopwatch chronoPrincipal;
        /// <summary>
        /// Delegate pour le chrono
        /// </summary>
        delegate void DLGC();
        /// <summary>
        /// event pour stoper le chrono
        /// </summary>
        private event DLGC evt;
        /// <summary>
        /// event pour toutes les méthodes de cryptage
        /// </summary>
        private event DLGC evtTrouver;
        /// <summary>
        /// Sauvegarde du temps
        /// </summary>
        private string temps ="";


        /// <summary>
        /// Cherche la meileur clé probable pour le contenu
        /// </summary>
        /// <param name="contenu">text décodé</param>
        /// <returns>les 5 meilleurs Cl_decode</returns>
        public List<Cl_decode> trouverCle(string contenu)
        {
            DLGC d1 = new DLGC(this.LancerChrono);
            evt = new DLGC(StopChrono);
            string echantillon;
            echantillon = echantillonner(contenu);

            //demarage du chrono
            Thread t1 = new Thread(new ThreadStart(d1.Invoke));
            t1.Start();
            List<Cl_decode> decodes = new List<Cl_decode>();
            for (int i = 0; i < 100000; i++)
            {
                Cl_decode decode = new Cl_decode(i, echantillon, langue,"Xor");
                decodes.Add(decode);
            }

            //foreach (Cl_decode x in decodes)
            //{
            Parallel.ForEach(decodes, (x) =>
            {
                x.decoder();

                //}
            });

            evt.Invoke();
            decodes.OrderByDescending((h) => h.pourcent).FirstOrDefault().seconde = temps;
            return decodes.OrderByDescending((h) => h.pourcent).Take(5).ToList();
        }


        /// <summary>
        /// Cherche le meileur cesar entre 4 et 9 pour le contenu
        /// </summary>
        /// <param name="contenu">message codé</param>
        /// <returns>les 5 meilleurs Cl_decode</returns>
        public List<Cl_decode> trouverCesar(string contenu)
        {
            DLGC d1 = new DLGC(this.LancerChrono);
            evt = new DLGC(StopChrono);
            string echantillon;
            echantillon = echantillonner(contenu);

            //demarage du chrono
            Thread t1 = new Thread(new ThreadStart(d1.Invoke));
            t1.Start();
            List<Cl_decode> decodes = new List<Cl_decode>();
            Cl_decode decode4 = new Cl_decode(4, echantillon, langue,"Cesar");
            decodes.Add(decode4);
            Cl_decode decode9 = new Cl_decode(9, echantillon, langue, "Cesar");
            decodes.Add(decode9);


            //foreach (Cl_decode x in decodes)
            //{
            Parallel.ForEach(decodes, (x) =>
            {
                x.decoderCesar();

                //}
            });

            evt.Invoke();
            decodes.OrderByDescending((h) => h.pourcent).FirstOrDefault().seconde = temps;
            return decodes.OrderByDescending((h) => h.pourcent).Take(5).ToList();
        }

        /// <summary>
        /// Cherche dans les 2 méthodes de cryptage
        /// </summary>
        /// <param name="contenu">texte à deécoder</param>
        /// <returns>les 5 meilleurs Cl_decode</returns>
        public List<Cl_decode> trouverCryptage(string contenu)
        {
            DLGC dTrouver = new DLGC(this.LancerChronoPrincipal);
            evtTrouver = new DLGC(StopChronoPrincipal);
            Thread tTrouver = new Thread(new ThreadStart(dTrouver.Invoke));
            tTrouver.Start();
            List<Cl_decode> decodeCesar = trouverCesar(contenu);
            List<Cl_decode> decodeXor = trouverCle(contenu);
            evtTrouver.Invoke();
            //decodeCesar.seconde = temps;
            //decodeXor.seconde = temps;

            List<Cl_decode> retour = decodeXor;
            retour.AddRange(decodeCesar);

            //if (decodeCesar.OrderByDescending((h) => h.pourcent).FirstOrDefault().pourcent > decodeXor.OrderByDescending((h) => h.pourcent).FirstOrDefault().pourcent)
            //{
            //    decodeCesar.OrderByDescending((h) => h.pourcent).FirstOrDefault().seconde = temps;
            //    return decodeCesar;
            //}
            //decodeXor.OrderByDescending((h) => h.pourcent).FirstOrDefault().seconde = temps;
            //return decodeXor;
            foreach (Cl_decode dec in retour)
            {
                dec.seconde = temps;
            }

            return retour.OrderByDescending((h) => h.pourcent).Take(5).ToList();

        }



        /// <summary>
        /// Lance le chrono
        /// </summary>
        private void LancerChrono()
        {
            chrono = Stopwatch.StartNew();
        }

        /// <summary>
        /// Lance le chrono principal
        /// </summary>
        private void LancerChronoPrincipal()
        {
            chronoPrincipal = Stopwatch.StartNew();
        }

        /// <summary>
        /// Lance le chrono principal
        /// </summary>
        private void StopChronoPrincipal()
        {
            chronoPrincipal.Stop();
            temps = chrono.Elapsed.Minutes + ":" + chrono.Elapsed.Seconds;

        }

        /// <summary>
        /// Stoper les chrono
        /// </summary>
        private void StopChrono()
        {
            chrono.Stop();
            temps = chrono.Elapsed.Minutes + ":" + chrono.Elapsed.Seconds;

        }

        /// <summary>
        /// Selectionne 150 caractères de textEntier si il peut sinon tout le text
        /// </summary>
        /// <param name="textEntier">text à échantionner</param>
        /// <returns>le texte choisi</returns>
        private string echantillonner(string textEntier)
        {
            int fin = 0;
            int debut = 0;

            if (textEntier.Length > 150)
            {
                fin = 150;
                Random r = new Random();
                debut = r.Next(0, textEntier.Length - 150);

            }
            else
            {
                fin = textEntier.Length;
                debut = 0;

            }


            Debug.WriteLine("debut du text: " + debut);
            return textEntier.Substring(debut, fin);


        }

        /// <summary>
        /// Constructeur surcharger
        /// </summary>
        /// <param name="languePara">choix de la langue, si la langue est null ou vide le choix all est appliqué</param>
        public Cl_workflow(string languePara)
        {
            if (languePara == null || languePara == "")
            {
                this.langue = "all";
            }
            else
            {
                this.langue = languePara;
            }



        }

        /// <summary>
        /// obligation d'utiliser la surcharge
        /// </summary>
        private Cl_workflow() { }




    }
}
